﻿using System;

namespace Glue.Internals
{
    internal partial class ObjectMemberFactory
    {
        private class ArrayMember : CollectionMemberBase
        {
            internal ArrayMember(IObjectMemberAccessor memberAccessor) : base(memberAccessor) {}

            protected override object InvokeSpecialGet(object toInvokeOn)
            {
                var array = InvokeGetOnActualObject(toInvokeOn);
                if (array==null)
                    return null;
                return new ArrayCollection((Array)array,this);

            }

            protected override void InvokeSpecialSet(object toInvokeOn, object toSet)
            {
                Array array = toSet==null?null:((ArrayCollection) toSet).GetArray();
                InvokeSetOnActualObject(toInvokeOn,array);
            }

            public override IGlueCollection CreateCollection(IGlueCollection collection)
            {
                return new ArrayCollection(Array.CreateInstance(MemberType.GetElementType(),collection.Count),this);
            }

            public override Type GetElementType()
            {
                return MemberType.GetElementType();
            }

            private class ArrayCollection : IGlueCollection
            {
                private readonly Array objects;
                private readonly ArrayMember creator;
                private int readPointer = -1;
                private int writePointer = 0;

                public ArrayCollection(Array objects, ArrayMember creator)
                {
                    this.objects = objects;
                    this.creator = creator;
                }

                public bool MoveNext()
                {
                    if (readPointer<objects.Length-1)
                    {
                        readPointer++;
                        return true;
                    }
                    return false;
                }

                public object Current
                {
                    get { return objects.GetValue(readPointer); }
                }

                public int Count
                {
                    get { return objects.Length; }
                }

                public void Add(object value)
                {
                    objects.SetValue(value,writePointer);
                    writePointer++;
                }

                public bool CreatedBy(ICollectionMember collectionMember)
                {
                    return collectionMember == creator;
                }

                public Array GetArray()
                {
                    return objects;
                }
            }
        }

        
    }
}
